﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SerialPortListener
{
    using System.IO.Ports;

    /// <summary>
    /// The serial port helper.
    /// </summary>
    public class SerialPortHelper : ISerialPortHelper
    {
        // Add this variable

        public  string RxString;
        public event EventHandler Lectura;

        /// <summary>
        /// Escribe el mBuffer en el puerto Serie conectado al 18.
        /// </summary>
        /// <param name="mBuffer">
        /// The m buffer.
        /// </param>
        /// <returns>
        /// True si no paso nada, false en caso de error.
        /// </returns>
        /// <exception cref="NotImplementedException">
        /// </exception>
        public bool WritePort(byte[] mBuffer)
        {
            if (!this.serialPort1.IsOpen)
            {
                return false;
            }

            this.serialPort1.Write(mBuffer, 0, mBuffer.Length);

            return true;
        }

        public bool WritePort(String mBuffer)
        {
            if (!this.ValidateArray(mBuffer))
            {
                return false;
            }

            if (mBuffer.Length != 12)
            {
                return false;
            }

            return WritePort(StringToByteArray(mBuffer));
        }

        SerialPort serialPort1 = new SerialPort();

        public bool DetectModule()
        {
            Console.WriteLine("Conectado . . .");
            serialPort1.DataReceived += new SerialDataReceivedEventHandler(this.serialPort1_DataReceived);
            var txt = string.Empty;
            var flag = false;
            int i = 1;
            while (!flag && i < 20)
            {
                try
                {
                    serialPort1.Close();
                    System.Threading.Thread.Sleep(500);
                    serialPort1.PortName = "COM" + i.ToString();
                    txt = "Traying Opening Port" + serialPort1.PortName;
                    serialPort1.BaudRate = 9600;
                    i++;
                    serialPort1.Open();
                    if (serialPort1.IsOpen)
                    {
                        flag = Comprobar18();
                        Console.WriteLine("Conectado - Port Detected: " + serialPort1.PortName + " BaudRate: " + serialPort1.BaudRate + "Por Open: " + serialPort1.IsOpen);
                        return true;
                    }
                }
                catch (System.IO.IOException exception)
                {
                    //el puerto probado no existe...solo continuo buscando
                }
            }

            Console.WriteLine("Fallo la conexión");

            return false;

        }

        byte[] ISerialPortHelper.StringToByteArray(string hex)
        {
            return StringToByteArray(hex);
        }


        /// <summary>
        /// The comprobar 18.
        /// </summary>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        private bool Comprobar18()
        {
            // If the port is closed, don't try to send a character.

            if (!serialPort1.IsOpen) return false;

            // If the port is Open, declare a char[] array with one element.

            byte[] mBuffer2 = StringToByteArray("0a0b0c0d0e0f");

            serialPort1.Write(mBuffer2, 0, mBuffer2.Length);

            // Load element 0 with the key character.



            // Send the one character buffer.
            //serialPort1.Write(buff, 0, 1);

            System.Threading.Thread.Sleep(500);

            return !String.IsNullOrEmpty(RxString);
        }

        public static byte[] StringToByteArray(string hex)
        {
            return Enumerable.Range(0, hex.Length)
                             .Where(x => x % 2 == 0)
                             .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
                             .ToArray();
        }

        public bool ClosePort()
        {
            if (serialPort1.IsOpen)
            {
                serialPort1.Close();
                return true;
            }

            return false;
        }

        /// <summary>
        /// The serial port 1_ data received.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void serialPort1_DataReceived
          (object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            byte[] bufferReader = new byte[6];
            RxString = "";
            if (serialPort1.IsOpen)
            {

                RxString = serialPort1.ReadExisting();

                if (Lectura != null)
                {
                    Lectura(this, new EventArgs());
                }
            }

        }

        /// <summary>
        /// The read existing.
        /// </summary>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string ReadExisting()
        {
            return this.RxString;
        }

        private bool ValidateArray(string aBytes)
        {
            foreach (var aByte in aBytes)
            {
                if (!this.validateCaracterHexa(Convert.ToChar(aByte)))
                {
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// The validate caracter hexa.
        /// </summary>
        /// <param name="a">
        /// The a.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        private bool validateCaracterHexa(char a)
        {
            if (a == 'a' || a == 'b' || a == 'c' || a == 'd' || a == 'e' || a == 'f' || a == '0' || a == '1' || a == '2'
                || a == '3' || a == '4' || a == '5' || a == '6' || a == '7' || a == '8' || a == '9')
            {
                return true;
            }
            return false;
        }
    }
}
